package com.j4dream.property.config;

import com.j4dream.property.dao.UserDao;
import com.j4dream.property.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class DbAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDao userDao;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
        String email = authentication.getName();
        String password = authentication.getCredentials().toString();

        if (StringUtils.isEmpty(email)) {
            throw new UsernameNotFoundException("User name cannot empty.");
        }

        if (StringUtils.isEmpty(password)) {
            throw new UsernameNotFoundException("Password cannot empty.");
        }

        UserDto u;
        if ((u = userDao.findOneByEmail(email)) == null) {
            throw new BadCredentialsException("Invalid user name");
        }

        if (!u.isAccountNonLocked()) {
            throw new BadCredentialsException("User is locked");
        }

        if (!u.isEnabled()) {
            throw new BadCredentialsException("User is disabled");
        }

        if (!passwordEncoder.matches(password, u.getPassword())) {
            userDao.updateLoginFailCountByEmail(email);
            throw new BadCredentialsException("Invalid password");
        }

        return new UsernamePasswordAuthenticationToken(
                u, u.getPassword(), u.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}
